// new Promise((resolve, reject) => {})
// var promise = new promise()
// 用法一、promise.then(res => {}, err => {})
// 用法二、promise.then(res => {}, err => {})
// 用法三、promise.then(res => {}).catch(err => {})
// 用法四、promise.then(res => {}).then(res => {}).catch(err => {})
(function(window){
	// 定义MyPromise的初始状态
	const PENDDING = 'pendding'; // 进行中
    const FULFILLED = 'fulfilled'; // 履行承诺
    const REJECTED = 'rejected'; // 拒绝承诺

	// 定义MyPromise构造函数
	function MyPromise(executor) {
		const self = this;
		self.status = PENDDING; //初始状态
        self.data = undefined; // 初始值
        self.callbacks = []; // 待执行异步回调函数的数组

        // 当状态变为'fulfilled'时，立即执行resolve
		function resolve(value) {
			// 如果状态改变，就不可能在修改了，所以要禁止往下执行
			if (self.status !== PENDDING) return;

			self.status = FULFILLED;
            self.data = value;
            // 立即执行异步回调函数
            setTimeout(function() {
            	self.callbacks.forEach(obj => {
            		obj.onResolved(value)
            	})
            }, 0)
		}
		// 当状态变为'rejected'时，立即执行reject
		function reject(reason) {
			// 如果状态改变，就不可能在修改了，所以要禁止往下执行
			if (self.status !== PENDDING) return;

			self.status = REJECTED;
            self.data = reason;
            setTimeout(function() {
            	self.callbacks.forEach(obj => {
            		obj.onReject(reason)
            	})
            }, 0)
		}
		executor(resolve, reject)
	}

	// then方法,有两个入参
	// onResolved用来监听resolve的回调函数，必填
	// onReject用来监听reject的回调函数，选填，等价于catch
	// 返回一个新的Promise
	MyPromise.prototype.then = function (onResolved, onRejected) {
        const self = this;

        // 防止不穿成功或者失败的回调函数，给成功和失败都给一个默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : reason => {throw reason};
        
        return new MyPromise((resolve, reject) => { // 每次都返回一个新的Promise对象
            function handle(callback) {
                /* 
                    1、返回的Promise的结果是由onResolved/onrejected决定的
                    2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
                    3、返回的不是Promise对象 (该值就是Promise的返回结果)
                    4、抛出异常 异常的值为返回的结果
                */
                try {
                    const result = callback(self.data);
                    if (reject instanceof MyPromise) {
                        result.then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        resolve(result);
                    }

                } catch (error) {
                    reject(error);
                }
            }
            // 首先判断当前状态
            if (self.status === FULFILLED) {
                setTimeout(() => {
                    handle(onResolved)
                });

            } else if (self.status === REJECTED) {
                setTimeout(() => {
                    handle(onRejected)
                });

            } else if (self.status === PENDDING) {
                self.callbacks.push({
                    onResolved() {
                        handle(onResolved)
                    },
                    onRejected() {
                        handle(onRejected)
                    }
                })
            }
        })
    }

	// catch方法
	// onReject用来监听reject的回调函数，
	MyPromise.prototype.catch = function(onReject) {
		return this.then(null, onRejected);
	}

	// resolve\reject\all\race都是构造函数的私有方法，不能够被继承
	
	// value返回响应值
	MyPromise.resolve = function(value) {
		if (value instanceof MyPromise) return value;
    	return new MyPromise(resolve => resolve(value))  // 返回一个resolved状态的Promise对象
	}

	// reason返回错误响应值或者说给出拒绝理由
	MyPromise.reject = function (reason) {
	    return new MyPromise((resolve,reject) => reject(reason));  // 返回一个reject状态Promise对象
	}

	// promises，调用所有的promise实例，都返回resolve后返回resolve
	MyPromise.all = function(promises) {
		let promisesCount = 0
	    let values = new Array(promises.length);
	    return new MyPromise((resolve,reject)=>{
	        promises.forEach((promise,index)=>{
	            promise.then(value => {
	                promisesCount++;
	                values[index] = value;
	                if (promisesCount === promises.length){
	                    resolve(values);
	                }
	            },reason => {
	                reject(reason);
	            })
	        })
	    })
	}

	// promises，调用所有的promise实例，有一个是reject，则返回reject
	MyPromise.race = function(promises) {
		return new MyPromise((resolve, reject) => {
	      promises.forEach(promise => {
	        MyPromise.resolve(promise).then(value => {
	          resolve(value);
	        }, reason => {
	          reject(reason)
	        })
	      })
	    })
	}

	window.MyPromise = MyPromise;
})(window)